package edu.mbi.ucla.pdbsearch.parser;

import edu.mbi.ucla.pdbsearch.model.*;

import java.util.Collection;
import java.util.ArrayList;
import java.io.BufferedReader;
import java.io.Reader;
import java.io.IOException;

/**
 * User: Jason Nerothin (jasonnerothin at gmail dot com)
 * Date: Nov 7, 2006
 * Time: 8:36:52 AM
 */
public abstract class AbstractFileParser {

    private String pdbId;

    private Visitor visitor;

    private ArrayList<? extends AbstractCompound> compounds;
    private ArrayList<? extends AbstractKeyword> keywords;
    private ArrayList<? extends AbstractProtein> proteins;
    private ArrayList<? extends AbstractMutation> mutations;
    private ArrayList<? extends AbstractSynonym> synonyms;
    private ArrayList<? extends AbstractOrganism> organisms;
    private ArrayList<? extends AbstractCellLine> cellLines;
    private ArrayList<? extends AbstractPlasmid> plasmids;

    private AbstractPubmedId pubmedId;
    private AbstractArticle article;
    private AbstractJournal journal;

    private AbstractLineParser lineParser = new LineParser();

    public void parse(Reader input) throws ParserException {
        try {
            // first pass through the file... harvest whichever lines we can...
            BufferedReader reader = new BufferedReader(input);
            String line;
            while ((line = reader.readLine()) != null) {
                Visitable visitable = lineParser.parse(line);
                addToParserCollection(visitable);
            }
            visitAll();
        } catch (IOException ioe) {
            throw new ParserException(ioe);
        }
    }

    private void visitAll() {
        for( AbstractCompound compound : compounds )
            compound.accept(visitor);
        for( AbstractKeyword keyword : keywords )
            keyword.accept(visitor);
        for( AbstractProtein protein : proteins )
            protein.accept(visitor);
        for( AbstractMutation mutation : mutations)
            mutation.accept(visitor);
        for( AbstractSynonym synonym : synonyms)
            synonym.accept(visitor);
        for( AbstractOrganism organism : organisms )
            organism.accept(visitor);
        for( AbstractCellLine cellLine : cellLines )
            cellLine.accept(visitor);
        for( AbstractPlasmid plasmid : plasmids )
            plasmid.accept(visitor);
    }

    public abstract void addToParserCollection(Visitable visitable) throws ParserException;

    // this is a convenience method to extract a pubmed id from the parsed file...

    public abstract String getPDBId() throws ParserException;

    // The next four methods only apply when the structure is an Xray structure.
    // NMR structures should throw a ParserException for cases where there is no
    // place in the file for those values...

    public abstract AbstractSpaceGroup getSpaceGroup() throws ParserException;

    public abstract Float getResolution() throws ParserException;

    public abstract Float getRfree() throws ParserException;

    public abstract Float getRvalue() throws ParserException;

    // These three correspond to articles referenced from the PDB file...

    public abstract Collection<AbstractArticle> getArticles() throws ParserException;

    public abstract Collection<String> getPubmedIds() throws ParserException;

    public abstract Collection<AbstractAuthor> getAuthors() throws ParserException;

    // These three correspond to types we invented for our model...

    public abstract Collection<AbstractCompound> getCompounds() throws ParserException;

    public abstract Collection<AbstractProtein> getProteins() throws ParserException;

    public abstract Collection<AbstractKeyword> getKeywords() throws ParserException;

}
